package com.zkthink.ceres.pay.callback.service.impl;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
import com.wechat.pay.java.service.payments.jsapi.model.QueryOrderByOutTradeNoRequest;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.zkthink.base.R;
import com.zkthink.ceres.applet.commission.service.AppletCommissionService;
import com.zkthink.ceres.applet.order.domain.entity.AppletProductOrder;
import com.zkthink.ceres.applet.order.domain.entity.AppletServerOrder;
import com.zkthink.ceres.applet.order.mapper.AppletProductOrderMapper;
import com.zkthink.ceres.applet.order.mapper.AppletServerOrderMapper;
import com.zkthink.ceres.common.utils.QcodeUtil;
import com.zkthink.ceres.file.properties.FileServerProperties;
import com.zkthink.ceres.finance.dto.DepositJournalSaveDTO;
import com.zkthink.ceres.finance.dto.DepositPromotionDTO;
import com.zkthink.ceres.finance.dto.JournalDetailSaveDTO;
import com.zkthink.ceres.finance.entity.DepositJournal;
import com.zkthink.ceres.finance.enums.DepositStateEnum;
import com.zkthink.ceres.finance.enums.DepositTypeEnum;
import com.zkthink.ceres.finance.enums.JournalTypeEnum;
import com.zkthink.ceres.finance.enums.PaymentTypeEnum;
import com.zkthink.ceres.finance.service.DepositJournalService;
import com.zkthink.ceres.finance.service.JournalDetailService;
import com.zkthink.ceres.member.entity.Member;
import com.zkthink.ceres.member.service.MemberService;
import com.zkthink.ceres.order.dto.MoneyReturnCallbackDTO;
import com.zkthink.ceres.order.dto.PayOrderCallbackDTO;
import com.zkthink.ceres.order.entity.Order;
import com.zkthink.ceres.order.service.OrderService;
import com.zkthink.ceres.pay.callback.service.PayCallBackService;
import com.zkthink.ceres.pay.config.AlipayConfig;
import com.zkthink.ceres.pay.entity.AliReturnPayBean;
import com.zkthink.ceres.pay.service.PayService;
import com.zkthink.ceres.store.dao.StoreMapper;
import com.zkthink.ceres.store.entity.Store;
import com.zkthink.ceres.store.entity.StoreMember;
import com.zkthink.ceres.store.service.StoreService;
import com.zkthink.clh.order.entity.*;
import com.zkthink.context.BaseContextHandler;
import com.zkthink.database.mybatis.conditions.Wraps;
import com.zkthink.exception.BizException;
import com.zkthink.utils.StrPool;
import com.zkthink.zhl.order.dao.ChlConfigMapper;
import com.zkthink.zhl.order.dao.ChlMemberTichengMapper;
import com.zkthink.zhl.order.service.ChlCouponsService;
import com.zkthink.zhl.order.service.ChlOrderService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.zkthink.utils.DateUtils.DEFAULT_MONTH_FORMAT_SLASH;

/**
 * <p>
 *
 * </p>
 *
 * @author vivi.huang
 * @since 2020/5/28
 */
@Slf4j
@Service
@AllArgsConstructor
public class PayCallBackServiceImpl implements PayCallBackService {

    private PayService payService;
    private OrderService orderService;
    private JournalDetailService journalDetailService;
    private DepositJournalService depositJournalService;
    private ChlOrderService chlOrderService;
    @Autowired
    private MemberService memberService;
    @Autowired
    private StoreMapper storeMapper;
    @Autowired
    private ChlCouponsService chlCouponsService;
    @Resource
    private FileServerProperties fileProperties;
    @Autowired
    private ChlConfigMapper chlConfigMapper;
    @Autowired
    private ChlMemberTichengMapper chlMemberTichengMapper;
    @Autowired
    private StoreService storeService;

    @Autowired
    private AppletServerOrderMapper appletServerOrderMapper;

    @Autowired
    private AppletProductOrderMapper appletProductOrderMapper;

    @Resource
    private AppletCommissionService appletCommissionService;

    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    @Override
    public String handleOrderNotifyCallBack(HttpServletRequest request) {
        try {
            // 转为xml
            String xmlResult = toXml(request);
            log.info("开始执行[支付结果通知回调]:[{}]", xmlResult);
            // 解析xml业务字段
            WxPayOrderNotifyResult result = payService.parseOrderNotifyResult(xmlResult);

//            Optional<DepositPromotionDTO> depositPromotionDTO = getDepositPromotionDTO(result);
//
//            if (isDepositType(depositPromotionDTO)) {
//                return handleOrderNotifyCallBackForDeposit(request, result, xmlResult, depositPromotionDTO);
//            }
            return handleOrderNotifyCallBackForOrder(request, result, xmlResult);

        } catch (IOException e) {
            log.error("支付结果通知-转换xml-IO异常", e);
            return WxPayNotifyResponse.fail(e.getMessage());
        } catch (WxPayException e) {
            log.error("支付结果通知-解析xml异常", e);
            return WxPayNotifyResponse.fail(e.getMessage());
        }
    }


    private Optional<DepositPromotionDTO> getDepositPromotionDTO(WxPayOrderNotifyResult result) {
        String attach = result.getAttach();
        if (!StringUtils.isEmpty(attach)) {
            DepositPromotionDTO depositPromotionDTO = JSON.parseObject(attach, DepositPromotionDTO.class);
            return Optional.ofNullable(depositPromotionDTO);
        }
        return Optional.empty();
    }

    private String handleOrderNotifyCallBackForDeposit(HttpServletRequest request, WxPayOrderNotifyResult result, String xmlResult, Optional<DepositPromotionDTO> depositPromotionDTO) {
        createDepositJournal(result, depositPromotionDTO.get());
        return WxPayNotifyResponse.success("成功");
    }

    private String handleOrderNotifyCallBackForOrder(HttpServletRequest request, WxPayOrderNotifyResult result, String xmlResult) throws WxPayException {

        //判断返回状态
        if (!WxPayConstants.ResultCode.SUCCESS.equals(result.getResultCode())) {
            log.error(xmlResult);
            throw new WxPayException("微信通知支付失败！");
        }
        if (!WxPayConstants.ResultCode.SUCCESS.equals(result.getReturnCode())) {
            log.error(xmlResult);
            throw new WxPayException("微信通知支付失败！");
        }

        //判断订单是否存在
        ChlOrder order = getOrder(result.getOutTradeNo());
        if (!checkOrderExist(order)) {
            log.error("订单不存在 sn={}", result.getOutTradeNo());
            return WxPayNotifyResponse.fail("订单不存在 sn=" + result.getOutTradeNo());
        }

        //判断订单是否已处理过
        if (checkOrderProcessedBefore(order)) {
            log.warn("订单已经处理成功! 单号:[{}]", order.getOrderCode());
            return WxPayNotifyResponse.success("订单已经处理成功!");
        }

        //检查支付订单金额
        if (!checkOrderPrice(order, result)) {
            log.error("[{}] : 支付金额不符合 totalFee=[{}]", result.getOutTradeNo(), result.getTotalFee());
            return WxPayNotifyResponse.fail(result.getOutTradeNo() + " : 支付金额不符合 totalFee=" + result.getTotalFee());
        }

        //更新订单状态
        updateXsyOrderToPayed(order, result);
        log.info("更新订单状态成功 单号:[{}]", order.getOrderCode());

        //创建流水
        createJournal(result, order);
        log.info("创建流水成功 单号：[{}]", order.getOrderCode());
        /**
         * 更新用户信息
         */
        updateCashAndLove(order);
        log.info("更新用户信息", order.getOrderCode());

        return WxPayNotifyResponse.success("成功");
    }

    private void createJournal(WxPayOrderNotifyResult result, ChlOrder order) {
        createEnterAccountJournal(order);
    }

    /**
     * 保证金交易流水
     */
    private void createDepositJournal(WxPayOrderNotifyResult result, DepositPromotionDTO depositPromotionDTO) {
        try {
            DepositJournalSaveDTO depositJournal = new DepositJournalSaveDTO();
            depositJournal.setAmount(Long.valueOf(result.getTotalFee()));
            depositJournal.setDepositType(DepositTypeEnum.PROMOTION.getCode());
            depositJournal.setTransactionId(result.getTransactionId());
            depositJournal.setPromotionId(depositPromotionDTO.getPromotionId());
            depositJournal.setState(DepositStateEnum.FREEZES.getCode());
            depositJournal.setTenantCode(depositPromotionDTO.getTenantCode());
            depositJournalService.saveDepositJournal(depositJournal);
            log.info("创建保证金交易流水:transactionId:[{}], promotion:[{}]", result.getTransactionId(), "");
        } catch (Exception e) {
            log.error("创建保证金交易流水异常", e);
            throw new BizException("创建保证金交易流水异常");
        }
    }

    private boolean isDepositType(Optional<DepositPromotionDTO> result) {
        return result.map(r -> {
            log.info("DepositPromotionDTO:[{}]", JSON.toJSONString(r));
            return r.getDepositType().equals(DepositTypeEnum.PROMOTION.name());
        }).orElse(false);
    }

    @Transactional(rollbackFor = {Exception.class, RuntimeException.class})
    @Override
    public String handleRefundNotifyCallBack(HttpServletRequest request) {
        try {
            // 转为xml
            String xmlResult = toXml(request);

            log.info("开始执行[退款结果通知回调]:[{}]", xmlResult);

            // 解析xml业务字段
            WxPayRefundNotifyResult result = payService.parseRefundNotifyResult(xmlResult);

            //判断微信申请退款状态
            if (!WxPayConstants.ResultCode.SUCCESS.equals(result.getReturnCode())) {
                log.error(xmlResult);
                throw new WxPayException("微信申请退款失败！");
            }

            //更新订单状态
            ChlOrder order = getOrder(result.getReqInfo().getOutTradeNo());
            if (Objects.nonNull(order)) {
                return handleRefundNotifyCallBackForOrder(result, order);
            }
            return handleRefundNotifyCallBackForDeposit(result);


        } catch (IOException e) {
            log.error("支付结果通知-转换xml-IO异常", e);
            return WxPayNotifyResponse.fail(e.getMessage());
        } catch (WxPayException e) {
            log.error("支付结果通知-解析xml异常", e);
            return WxPayNotifyResponse.fail(e.getMessage());
        }
    }

    @Override
    public R wxSelectOrder(String id) {
        String orderCode = "";
        ChlOrder byId = chlOrderService.getById(id);
        AppletProductOrder appletProductOrder = null;
        AppletServerOrder appletServerOrder = null;
        if (byId != null) {
            orderCode = byId.getOrderCode();
        } else {
            appletProductOrder = appletProductOrderMapper.selectOne(new QueryWrapper<AppletProductOrder>().eq("order_code",id));
            if (appletProductOrder != null) {
                orderCode = appletProductOrder.getOrderCode();
            } else {
                appletServerOrder = appletServerOrderMapper.selectOne(new QueryWrapper<AppletServerOrder>().eq("order_code",id));
                if (appletServerOrder != null) {
                    orderCode = appletServerOrder.getOrderCode();
                }
            }
        }
        if (StringUtils.isEmpty(orderCode)) {
            return R.fail("订单不存在");
        }
        try {
            //私钥文件路径（本地自己测试看自己的私钥文件存放路径）
//            String filePath = "E:\\WXCertUtil\\llc\\apiclient_key.pem";
            String filePath ="/opt/llc/cert/apiclient_key.pem";
            // 一个商户号只能初始化一个配置，否则会因为重复的下载任务报错
            RSAAutoCertificateConfig config = new RSAAutoCertificateConfig.Builder()
                    .merchantId("1666915143")
                    .privateKeyFromPath(filePath)
                    .merchantSerialNumber("140DEA0F5B3FC9FB0B158EE29CECB62F2307CA74")
                    .apiV3Key("A6fG7K6jL8VwQ5RmP1nZyB4dC3HqT0aS")
                    .build();
            // 构建service
            JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(config).build();
            QueryOrderByOutTradeNoRequest queryOrderByOutTradeNoRequest = new QueryOrderByOutTradeNoRequest();
            queryOrderByOutTradeNoRequest.setMchid("1666915143");
            queryOrderByOutTradeNoRequest.setOutTradeNo(orderCode);
            Transaction transaction = service.queryOrderByOutTradeNo(queryOrderByOutTradeNoRequest);
            String string = transaction.getTradeState().toString();
            if (string.equals("SUCCESS")) {
                if (byId != null) {
                    //更新订单状态
                    updateXsyOrderToPayed(byId, new WxPayOrderNotifyResult());
                    log.info("更新订单状态成功 单号:[{}]", byId.getOrderCode());

                    //创建流水
                    createJournal(new WxPayOrderNotifyResult(), byId);
                    log.info("创建流水成功 单号：[{}]", byId.getOrderCode());
                    /**
                     * 更新用户信息
                     */
                    updateCashAndLove(byId);
                    log.info("更新用户信息", byId.getOrderCode());
                    return R.success("支付成功");
                }
                if (appletProductOrder != null){
                    appletProductOrder.setPayTime(new Date());
                    appletProductOrder.setPayStatus(2);
                    appletProductOrderMapper.updateById(appletProductOrder);
                }
                if (appletServerOrder != null){
                    appletServerOrder.setPayTime(new Date());
                    appletServerOrder.setPayStatus(2);
                    appletServerOrderMapper.updateById(appletServerOrder);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;

    }


    @Override
    public String handleOrderNotifyCallBackaliPay(HttpServletResponse response, AliReturnPayBean returnPay, HttpServletRequest req) {
        log.error("支付宝回调成功===" + checkSign(req));
        System.out.println(checkSign(req));
        System.out.println("支付宝回调成功");
        System.out.println(returnPay.toString());
        System.out.println(returnPay.getTrade_status());
        System.out.println(returnPay.getTrade_status().equals("TRADE_SUCCESS"));
        if (!checkSign(req)) {
            System.out.println("支付宝校验失败" + returnPay.getOut_trade_no());
            return "支付宝校验失败";
        }
        try {
            ChlOrder order = getOrder(returnPay.getOut_trade_no());
            System.out.println(returnPay.getTrade_status());
            System.out.println(returnPay.getTrade_status().equals("TRADE_SUCCESS"));
            System.out.println("orderStatus" + (order.getOrderStatus() == 1));
            if (order.getOrderStatus() == 1) {
                if (returnPay.getTrade_status().equals("TRADE_SUCCESS")) {
                    //支付宝支付成功
                    //更新订单状态
                    System.out.println("支付流程一");
                    return handleOrderNotifyCallBackForOrderAliPay(returnPay);
                } else {
                    order.setOrderStatus(2);
                    chlOrderService.updateById(order);
                }
            }

//            if (returnPay.getTrade_status().equals("TRADE_CLOSED")) {
//                //支付宝订单退款完毕，交易关闭
//                return handleRefundNotifyCallBackaliPay(order, returnPay, req);
//            }
            System.out.println("2");

        } catch (Exception e) {
            e.printStackTrace();
            return "failture";
        }
        return "";
    }

    private String handleOrderNotifyCallBackForOrderAliPay(AliReturnPayBean returnPay) {
        //判断订单是否存在
        ChlOrder order = getOrder(returnPay.getOut_trade_no());
        if (!checkOrderExist(order)) {
            System.out.println("5");
            log.error("订单不存在 sn={}", returnPay.getOut_trade_no());
            return WxPayNotifyResponse.fail("订单不存在 sn=" + returnPay.getOut_trade_no());
        }
        //判断订单是否已处理过
        if (checkOrderProcessedBefore(order)) {
            System.out.println("6");
            log.warn("订单已经处理成功! 单号:[{}]", order.getOrderCode());
            return WxPayNotifyResponse.success("订单已经处理成功!");
        }
        //检查支付订单金额
        if (!checkOrderPrice(order, returnPay)) {
            System.out.println("7");
            log.error("[{}] : 支付金额不符合 totalFee=[{}]", returnPay.getOut_trade_no(), Double.parseDouble(returnPay.getTotal_amount()) * 100);
            return WxPayNotifyResponse.fail(returnPay.getOut_trade_no() + " : 支付金额不符合 totalFee=" + returnPay.getTotal_amount() + "=" + order.toString() + "==" + returnPay.toString());
        }
        //更新订单状态
        updateXsyOrderToPayed(order, returnPay);
        //创建流水
        System.out.println("10");
        createJournal(null, order);
        log.info("创建流水成功 单号：[{}]", order.getOrderCode());

        //更新消费金和钱包
        updateCashAndLove(order);


        return WxPayNotifyResponse.success("成功");
    }

    /**
     * 更新消费金和钱包
     */
    @Transactional
    public void updateCashAndLove(ChlOrder order) {
        Member member = memberService.getById(order.getMid());

        //购买vip
        if (order.getOrderType() == 1) {
            //支付后回调参数逻辑，支付申请未完成，暂时放在购买里
            int vipDay = order.getLoveNum().intValue() * 30;
            if (member.getVipTime() != null) {
                if (member.getVipTime().isAfter(LocalDateTime.now())) {
                    member.setVipTime(member.getVipTime().plusDays(vipDay));
                } else {
                    member.setVipTime(LocalDateTime.now().plusDays(vipDay));
                }
            } else {
                member.setVipTime(LocalDateTime.now().plusDays(vipDay));
            }
            member.setLevel(1);
            memberService.updateAllById(member);
            //添加提成信息
            appletCommissionService.addCommission(member.getId(),order.getPaySum());
//            //提成
//            if (member.getReferPhone() != null) {
//                Member byOpenid = memberService.findByphone(member.getReferPhone());
//                //提成
//                ChlMemberTicheng chlMemberTicheng = new ChlMemberTicheng();
//                chlMemberTicheng.setUserid(order.getMid());
//                chlMemberTicheng.setXiaofei(order.getPaySum());
//                chlMemberTicheng.setHeadimg(member.getHeadimg());
//                chlMemberTicheng.setNickname(member.getNickname());
//                chlMemberTicheng.setMid(byOpenid.getId());
//                ChlConfig byparameterUnique = chlConfigMapper.findByparameterUnique("tg.tc");
//                if (byparameterUnique != null) {
//                    BigDecimal divide = byparameterUnique.getParameterValue().divide(new BigDecimal(100));
//                    chlMemberTicheng.setTicheng(order.getPaySum().multiply(divide));
//                    System.out.println("我的余额=" + byOpenid.getBalance() + "==提成金额=" + chlMemberTicheng.getTicheng());
//                    //余额加上提成
//                    byOpenid.setBalance(byOpenid.getBalance().add(chlMemberTicheng.getTicheng()));
//                    byOpenid.setTichneg(byOpenid.getTichneg().add(chlMemberTicheng.getTicheng()));
//                    System.out.println("我的余额=" + byOpenid.getBalance());
//                    memberService.updateById(byOpenid);
//                    chlMemberTichengMapper.insert(chlMemberTicheng);
//                }
//            }

        }
        // 充值消费金
        if (order.getOrderType() == 2) {
            //    判断用户是否vip
            if (member.getVipTime().isAfter(LocalDateTime.now())) {
                if (member.getCoupons() == null){
                    member.setCoupons(new BigDecimal(0));
                }
                ChlCoupons recharge = chlCouponsService.findRecharge(order.getPaySum());
                if (recharge != null) {
                    member.setCoupons(member.getCoupons().add(recharge.getCoupons()));
                }
//                member.setBalance(member.getBalance().add(order.getPaySum()));
            }
            memberService.updateAllById(member);
        }
        //充值余额
        if (order.getOrderType() == 5) {
            if (member.getBalance() == null){
                member.setBalance(new BigDecimal(0));
            }
            member.setBalance(member.getBalance().add(order.getPaySum()));
            memberService.updateAllById(member);
        }
        //入住费
        if (order.getOrderType() == 3) {
            Integer sum = order.getLoveNum().intValue();
            int sumDay = sum * 30;
            Store store = storeMapper.myScore(member.getUserType(), member.getId());

            if (store.getExpirationime() != null) {
                if (store.getExpirationime().isAfter(LocalDateTime.now())) {

                    store.setExpirationime(store.getExpirationime().plusDays(sumDay));
                } else {

                    store.setExpirationime(LocalDateTime.now().plusDays(sumDay));
                }
            } else {

                store.setExpirationime(LocalDateTime.now().plusDays(sumDay));
            }

            storeMapper.updateAllById(store);
        }
        //购买服务
        if (order.getOrderType() == 4) {
            member.setCoupons(order.getOrderSum().subtract(order.getOrderSum()));
            order.setCodeUrl(qRCodeUrl(order.getOrderCode()));
            order.setExamine(1);
            chlOrderService.updateById(order);
            memberService.updateAllById(member);
        }

    }

    //生成二维码图片地址
    public String qRCodeUrl(String content) {
        String fileName = UUID.randomUUID().toString() + StrPool.DOT + "png";
        //日期文件夹
        String relativePath = Paths.get(LocalDate.now().format(DateTimeFormatter.ofPattern(DEFAULT_MONTH_FORMAT_SLASH))).toString();
        // web服务器存放的绝对路径
        String absolutePath = Paths.get(fileProperties.getStoragePath(), relativePath).toString();
        QcodeUtil.getQRCode(content, Paths.get(absolutePath, fileName).toString());
        String url = new StringBuilder(fileProperties.getUriPrefix())
                .append(relativePath)
                .append(StrPool.SLASH)
                .append(fileName)
                .toString();

        //替换掉windows环境的\路径
        url = StrUtil.replace(url, "\\\\", StrPool.SLASH);
        url = StrUtil.replace(url, "\\", StrPool.SLASH);
        return url;
    }

    private void updateXsyOrderToPayed(ChlOrder order, WxPayOrderNotifyResult result) {
        try {
            QueryWrapper<AppletProductOrder> appletProductOrderQueryWrapper = new QueryWrapper<>();
            appletProductOrderQueryWrapper.eq("order_code", order.getOrderCode());
            AppletProductOrder appletProductOrder = appletProductOrderMapper.selectOne(appletProductOrderQueryWrapper);

            QueryWrapper<AppletServerOrder> appletServerOrderQueryWrapper = new QueryWrapper<>();
            appletServerOrderQueryWrapper.eq("order_code", order.getOrderCode());
            AppletServerOrder serverOrder = appletServerOrderMapper.selectOne(appletServerOrderQueryWrapper);

            if (appletProductOrder != null) {
                appletProductOrder.setPayTime(new Date());
                appletProductOrder.setPayStatus(2);
                appletProductOrderMapper.updateById(appletProductOrder);
            } else if (serverOrder != null) {
                serverOrder.setPayTime(new Date());
                serverOrder.setPayStatus(2);
                appletServerOrderMapper.updateById(serverOrder);
            } else {
                order.setPayTime(LocalDateTime.now());
                order.setOrderStatus(3);
                chlOrderService.updateById(order);
            }
        } catch (Exception e) {
            log.error("支付通知回调-订单回调异常,单号: [{}]", order.getOrderCode(), e);
            throw new BizException("支付通知回调-订单回调异常");
        }
    }

    private void updateXsyOrderToPayed(ChlOrder order, AliReturnPayBean returnPay) {
        try {
            order.setPayTime(LocalDateTime.now());
            order.setOrderStatus(3);
            chlOrderService.updateById(order);
        } catch (Exception e) {
            log.error("支付通知回调-订单回调异常,单号: [{}]", order.getOrderCode(), e);
            throw new BizException("支付通知回调-订单回调异常");
        }
    }

    private String handleRefundNotifyCallBackForDeposit(WxPayRefundNotifyResult result) {
        updateRefundDepositJournal(result);
        return WxPayNotifyResponse.success("成功");
    }

    private String handleRefundNotifyCallBackForOrder(WxPayRefundNotifyResult result, ChlOrder order) {
//        updateOrderRefundCallback(result);
//        log.info("更新订单退款回调成功,单号:[{}]", result.getReqInfo().getOutTradeNo());
//
//        //创建流水
//        createRefundJournal(order, result);
//        log.info("创建买家退款流水成功:单号:[{}]", result.getReqInfo().getOutTradeNo());
        return WxPayNotifyResponse.success("成功");
    }

    private void updateOrderRefundCallback(WxPayRefundNotifyResult result) {
        try {
            MoneyReturnCallbackDTO moneyReturnCallbackDTO = new MoneyReturnCallbackDTO();
            moneyReturnCallbackDTO.setReturnCode(result.getReqInfo().getOutRefundNo());
            moneyReturnCallbackDTO.setRefundFee(Long.valueOf(result.getReqInfo().getRefundFee()));
            moneyReturnCallbackDTO.setThirdReturnNo(result.getReqInfo().getRefundId());
            orderService.moneyReturnCallback(moneyReturnCallbackDTO);
        } catch (Exception e) {
            log.error("退款通知-更新订单回调异常,退款单号:[{}]", result.getReqInfo().getOutRefundNo(), e);
            throw new BizException("退款通知-更新订单回调异常");
        }
    }

    /**
     * 创建退款流水
     *
     * @param order
     * @param result
     */
    private void createRefundJournal(Order order, WxPayRefundNotifyResult result) {
        createRefundJournalOfOrder(order, result);
    }

    private void updateRefundDepositJournal(WxPayRefundNotifyResult result) {
        try {
            depositJournalService.updateRefundState(result.getReqInfo().getTransactionId());
            log.info("更新保证金退回交易流水:交易流水号:[{}]", result.getReqInfo().getTransactionId());
        } catch (Exception e) {
            log.error("更新保证金退回交易流水异常", e);
            throw new BizException("更新保证金退回交易流水异常");
        }
    }


    private boolean isPromotionOrder(Order order) {
        return !Objects.isNull(order.getPromotionId()) && order.getPromotionId() > 0;
    }

    private void createRefundJournalOfOrder(Order order, WxPayRefundNotifyResult result) {
        JournalDetailSaveDTO dto = new JournalDetailSaveDTO();
        dto.setPaymentType(PaymentTypeEnum.PAY_OUT.getCode());
        dto.setJournalType(JournalTypeEnum.REFUND.getCode());
        dto.setAmount(Long.valueOf(result.getReqInfo().getRefundFee()));
        dto.setOrderCode(order.getOrderCode());
        dto.setTenantCode(order.getTenantCode());
        journalDetailService.saveJournalDetail(dto);
    }

    private ChlOrder getOrder(String outTradeNo) {
        QueryWrapper<ChlOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_code", outTradeNo);
        ChlOrder one = chlOrderService.getOne(queryWrapper);
        if (one == null) {
            QueryWrapper<AppletServerOrder> appletServerOrderQueryWrapper = new QueryWrapper<>();
            appletServerOrderQueryWrapper.eq("order_code", outTradeNo);
            AppletServerOrder serverOrder = appletServerOrderMapper.selectOne(appletServerOrderQueryWrapper);
            if (serverOrder != null) {
                Member member = memberService.findById(serverOrder.getMid());
                one = new ChlOrder();
                one.setMid(serverOrder.getMid());
                one.setOrderCode(serverOrder.getOrderCode());
                one.setOrderStatus(serverOrder.getPayStatus());
                one.setOrderType(4);
                one.setMemberAccount(member.getAccount());
                one.setOrderSum(serverOrder.getCosts());
                one.setPaySum(serverOrder.getPaySum());
                one.setNotes(serverOrder.getOrderRamark());
                one.setPrepayId(serverOrder.getPrepayId());
                one.setPayTime(serverOrder.getPayTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
                one.setPayChannel(serverOrder.getPayChannel() == 1 ? 1 : 2);
                one.setPayNum(serverOrder.getPayNum());
                one.setCodeUrl(serverOrder.getCodeUrl());
                one.setStoreId(serverOrder.getStoreId());
                one.setCoupons(serverOrder.getCoupons());
                one.setProjectid(serverOrder.getServerId());
                one.setPhone(member.getPhone());
            }
            QueryWrapper<AppletProductOrder> appletProductOrderMapperQueryWrapper = new QueryWrapper<>();
            appletProductOrderMapperQueryWrapper.eq("order_code", outTradeNo);
            AppletProductOrder productOrder = appletProductOrderMapper.selectOne(appletProductOrderMapperQueryWrapper);
            if (productOrder != null) {
                Member member = memberService.findById(productOrder.getMid());
                one = new ChlOrder();
                one.setMid(productOrder.getMid());
                one.setOrderCode(productOrder.getOrderCode());
                one.setOrderStatus(productOrder.getPayStatus());
                one.setOrderType(4);
                one.setMemberAccount(member.getAccount());
                one.setOrderSum(productOrder.getCosts());
                one.setPaySum(productOrder.getPaySum());
                one.setNotes(productOrder.getOrderRamark());
                one.setPrepayId(productOrder.getPrepayId());
                one.setPayTime(productOrder.getPayTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime());
                one.setPayChannel(productOrder.getPayChannel() == 1 ? 1 : 2);
                one.setPayNum(productOrder.getPayNum());
                one.setCodeUrl(productOrder.getCodeUrl());
                one.setStoreId(productOrder.getStoreId());
                one.setCoupons(productOrder.getCoupons());
                one.setProjectid(productOrder.getProductId());
                one.setPhone(member.getPhone());
            }
        }
        return one;
    }

    private void createEnterAccountJournal(ChlOrder order) {

        System.out.println("11");
        log.info("创建买家入账流水单号:[{}]", order.getOrderCode());

        JournalDetailSaveDTO dto = new JournalDetailSaveDTO();
        dto.setPaymentType(PaymentTypeEnum.IM_COME.getCode());
        dto.setJournalType(JournalTypeEnum.ENTER_ACCOUNT.getCode());
        dto.setAmount(order.getPaySum().longValue());
        dto.setOrderCode(order.getOrderCode());
        dto.setEntryTime(LocalDateTime.now());
        dto.setTenantCode("admin");
        journalDetailService.saveJournalDetail(dto);
    }

    private boolean checkOrderExist(ChlOrder order) {
        return null != order;
    }

    private boolean checkOrderProcessedBefore(ChlOrder order) {
        //状态为待发货之后的状态证明已经付款过了
        return order.getOrderStatus().intValue() == 2;
    }

    private boolean checkOrderPrice(ChlOrder order, WxPayOrderNotifyResult result) {
        return (order.getOrderSum().multiply(new BigDecimal(100)).intValue() == result.getTotalFee());
    }

    private boolean checkOrderPrice(ChlOrder order, AliReturnPayBean returnPay) {
        return (order.getOrderSum().compareTo(new BigDecimal(returnPay.getTotal_amount())) == 0);
    }

    private void updateOrderToPayed(Order order, WxPayOrderNotifyResult result) {
        try {
            PayOrderCallbackDTO payOrderCallbackDTO = new PayOrderCallbackDTO();
            payOrderCallbackDTO.setOrderCode(order.getOrderCode());
            payOrderCallbackDTO.setPayTime(LocalDateTime.now());
            payOrderCallbackDTO.setPayNum(result.getTransactionId());
            orderService.payOrderCallBack(payOrderCallbackDTO);
        } catch (Exception e) {
            log.error("支付通知回调-订单回调异常,单号: [{}]", order.getOrderCode(), e);
            throw new BizException("支付通知回调-订单回调异常");
        }
    }

    private String toXml(HttpServletRequest request) throws IOException {
        return IOUtils.toString(request.getInputStream(), request.getCharacterEncoding());
    }

    public static boolean checkSign(HttpServletRequest req) {
        Map<String, String[]> requestMap = req.getParameterMap();
        Map<String, String> paramsMap = new HashMap<>();
//
//                paramsMap.put("gmt_create","2022-06-14 19:55:50");
//        paramsMap.put("charset","utf-8");
//        paramsMap.put("seller_email","2399076141@qq.com");
//        paramsMap.put("subject","购买服务");
//        paramsMap.put("sign","IaKmsrmeEJSpDqP5kQP8nDbOq3iV8U1tAN27rEoiqfZg/WauB+UowTII01B0dZTCjE67bw3maHraa9nYsxlPr1nZmYPArgbk3pNZEzpqKlAoNkAqfUtV4EV44QvqCmERV9Iyfu5G6Pi1aOnV2iLwxAKN/uNhGpnVgbDytnXJMdXPhhxn0I4a9J21iekPKTNblCBmOmK0e2sGEm2XL0tWSCOlHen/y8jKolS1fTYw4IxeS4NOzz34yfG/JN/FlDrxbOk/Dl+97on84hkdVPgTxAd2b0JhdRlQlTvg8iRIo2t/wLEPGgPdZm/nTCy+UI1DA+peCGZ9KWsvcNgfUI7tHQ==");
//                paramsMap.put("body","购买服务");
//       paramsMap.put("buyer_id","2088702610553911");
//       paramsMap.put("invoice_amount","0.01");
//       paramsMap.put("notify_id","2022061400222204417053911420769425");
//       paramsMap.put("fund_bill_list","[{\"amount\":\"0.01\",\"fundChannel\":\"ALIPAYACCOUNT\"}]");
//       paramsMap.put("notify_type","TRADE_SUCCESS");
//       paramsMap.put("trade_status","0.01");
//       paramsMap.put("receipt_amount","");
//       paramsMap.put("buyer_pay_amount","0.01");
//       paramsMap.put("app_id","2021003130642530");
//       paramsMap.put("sign_type","RSA2");
//       paramsMap.put("seller_id","2088441429435970");
//       paramsMap.put("gmt_payment","2022-06-14 20:44:16");
//       paramsMap.put("notify_time","2022-06-14 21:09:04");
//       paramsMap.put("version","1.0");
//       paramsMap.put("out_trade_no","20220614204344000000000000000001");
//       paramsMap.put("total_amount","0.01");
//       paramsMap.put("trade_no","2021003130642530");
//       paramsMap.put("auth_app_id","");
//       paramsMap.put("buyer_logon_id","15060682689");
//       paramsMap.put("point_amount","0.00");
        requestMap.forEach((key, values) -> {
            String strs = "";
            for (String value : values) {
                strs = strs + value;
            }
            System.out.println(("key值为" + key + ";value为：" + strs));
            paramsMap.put(key, strs);
        });

        try {
            return AlipaySignature.rsaCheckV1(paramsMap, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type);
        } catch (AlipayApiException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println(e);
            System.out.println("*********************验签失败********************");
            return false;
        }
    }
}
